"""
MCPy配置管理

处理MCPy项目的配置文件加载和管理。
"""

import json
from pathlib import Path
from typing import Dict, Any, Optional, Union, List


def load_config(config_path: Union[str, Path]) -> Dict[str, Any]:
    """加载配置文件"""
    config_path = Path(config_path)

    if not config_path.exists():
        raise FileNotFoundError(f"配置文件不存在: {config_path}")

    # 根据文件扩展名确定格式
    if config_path.suffix.lower() == ".json":
        return load_json_config(config_path)
    else:
        raise ValueError(f"不支持的配置文件格式: {config_path.suffix}")


def load_json_config(config_path: Path) -> Dict[str, Any]:
    """加载JSON配置文件"""
    try:
        with open(config_path, "r", encoding="utf-8") as f:
            return json.load(f)
    except json.JSONDecodeError as e:
        raise ValueError(f"JSON配置文件格式错误: {e}")
    except Exception as e:
        raise ValueError(f"读取配置文件失败: {e}")


def get_default_config() -> Dict[str, Any]:
    """获取默认配置"""
    return {
        "project": {
            "name": "mcpy_project",
            "version": "1.0.0",
            # 注意：命名空间现在通过 @namespace 装饰器指定，不再在配置中设置
            "source_patterns": ["**/*.py"],
            "exclude_patterns": ["__pycache__/**", ".*/**", "build/**", "dist/**"],
        },
        "compiler": {
            "output_dir": "generated",
            "source_root": ".",  # 用于计算包路径
            "format_code": True,
            "optimize": True,
            "verbose": False,
            "performance_stats": False,  # 是否输出性能统计
            "memory_stats": False,  # 是否输出内存统计
            "strict_typing": False,  # 是否强制要求类型注解
            "allow_missing_types": False,  # 是否允许缺少类型注解（兼容模式）
            "stubs_directories": [],  # 额外的stubs目录列表
        },
        "types": {"custom_types": []},
        "templates": {"custom_templates": []},
    }


def merge_config(
    base_config: Dict[str, Any], override_config: Dict[str, Any]
) -> Dict[str, Any]:
    """合并配置"""
    result = base_config.copy()

    for key, value in override_config.items():
        if key in result and isinstance(result[key], dict) and isinstance(value, dict):
            result[key] = merge_config(result[key], value)
        else:
            result[key] = value

    return result


def save_config(config: Dict[str, Any], config_path: Union[str, Path]):
    """保存配置到文件"""
    config_path = Path(config_path)

    # 根据文件扩展名确定格式
    if config_path.suffix.lower() == ".json":
        save_json_config(config, config_path)
    else:
        raise ValueError(f"不支持的配置文件格式: {config_path.suffix}")


def save_json_config(config: Dict[str, Any], config_path: Path):
    """保存JSON配置文件"""
    try:
        with open(config_path, "w", encoding="utf-8") as f:
            json.dump(config, f, ensure_ascii=False, indent=2)
    except Exception as e:
        raise ValueError(f"保存配置文件失败: {e}")


class ConfigManager:
    """配置管理器"""

    def __init__(self, config_path: Optional[Union[str, Path]] = None):
        self.config_path = Path(config_path) if config_path else None
        self.config = get_default_config()

        if self.config_path and self.config_path.exists():
            user_config = load_config(self.config_path)
            self.config = merge_config(self.config, user_config)

    def get(self, key_path: str, default: Any = None) -> Any:
        """获取配置值，支持点分路径"""
        keys = key_path.split(".")
        value = self.config

        for key in keys:
            if isinstance(value, dict) and key in value:
                value = value[key]
            else:
                return default

        return value

    def set(self, key_path: str, value: Any):
        """设置配置值，支持点分路径"""
        keys = key_path.split(".")
        config = self.config

        for key in keys[:-1]:
            if key not in config:
                config[key] = {}
            config = config[key]

        config[keys[-1]] = value

    def save(self, config_path: Optional[Union[str, Path]] = None):
        """保存配置到文件"""
        save_path = Path(config_path) if config_path else self.config_path

        if not save_path:
            raise ValueError("没有指定配置文件路径")

        save_config(self.config, save_path)

    def reload(self):
        """重新加载配置"""
        if self.config_path and self.config_path.exists():
            user_config = load_config(self.config_path)
            self.config = merge_config(get_default_config(), user_config)


def create_default_config_file(config_path: Union[str, Path]):
    """创建默认配置文件"""
    config_path = Path(config_path)
    default_config = get_default_config()

    # 确保目录存在
    config_path.parent.mkdir(parents=True, exist_ok=True)

    # 保存配置
    save_config(default_config, config_path)

    print(f"已创建默认配置文件: {config_path}")


def validate_config(config: Dict[str, Any]) -> List[str]:
    """验证配置的有效性"""
    errors = []

    # 验证必需的字段
    required_fields = ["project.name", "compiler.output_dir"]

    for field in required_fields:
        keys = field.split(".")
        value = config

        for key in keys:
            if not isinstance(value, dict) or key not in value:
                errors.append(f"缺少必需的配置字段: {field}")
                break
            value = value[key]

    # 验证类型
    type_validations = {
        "project.name": str,
        "project.version": str,
        "project.namespace": str,
        "compiler.output_dir": str,
        "compiler.format_code": bool,
        "compiler.optimize": bool,
        "compiler.verbose": bool,
    }

    for field, expected_type in type_validations.items():
        keys = field.split(".")
        value = config

        try:
            for key in keys:
                value = value[key]

            if not isinstance(value, expected_type):
                errors.append(
                    f"配置字段 {field} 类型错误，期望 {expected_type.__name__}，实际 {type(value).__name__}"
                )
        except (KeyError, TypeError):
            # 字段不存在或类型错误，已在必需字段检查中处理
            pass

    return errors
